<template>
  <n-modal v-model:show="visible" :title="title" display-directive="if" :bordered="false" preset="card" class="w-500px"
    size="huge" :closable="false">
    <n-form ref="formRef" :model="formData" :label-width="80" :rules="rules" label-placement="left" class="fi-w">
      <n-form-item label="角色名" path="roleName">
        <n-input v-model:value="formData.roleName" clearable />
      </n-form-item>
      <n-form-item label="标识符" path="roleKey">
        <n-input v-model:value="formData.roleKey" clearable />
      </n-form-item>
      <n-form-item label="状态" path="status">
        <n-radio-group v-model:value="formData.status">
          <n-space>
            <n-radio label="启用" :value="statusKeyOf.Yse" />
            <n-radio label="禁用" :value="statusKeyOf.No" />
          </n-space>
        </n-radio-group>
      </n-form-item>
      <n-form-item label="数据范围" path="dataScope">
        <n-select v-model:value="formData.dataScope" :options="dataOptions" />
      </n-form-item>
      <n-form-item label="部门范围" path="deptIds" v-if="formData.dataScope == '2'">
        <n-tree-select :options="deptTree" label-field="name" key-field="id" children-field="children" filterable
          v-model:value="formData.deptIds" clearable :cascade="true" :checkable="true" :default-expand-all="true"
          multiple />
      </n-form-item>
      <n-form-item label="绑定菜单" path="menuIds">
        <n-button @click="() => menuTreeActive = true">页面选择</n-button>
      </n-form-item>
      <n-form-item label="角色首页" path="homePage">
        <n-tree-select :options="menuPageTree" label-field="name" key-field="menuKey" children-field="children"
          filterable check-strategy="child" v-model:value="formData.homePage" clearable :checkable="true"
          :default-expand-all="true" />
      </n-form-item>
    </n-form>
    <n-space justify="center">
      <n-button type="primary" :loading="loading" @click="handleSubmitForm">确定</n-button>
      <n-button @click="hendleCloseModal" :loading="loading">取消</n-button>
    </n-space>
    <n-drawer v-model:show="menuTreeActive" :width="500" placement="right" display-directive="show">
      <n-drawer-content title="绑定菜单">
        <n-tree :data="menuTree" max-tag-count="responsive" label-field="name" key-field="id" ref="roleMenuSelectRef"
          children-field="children" filterable cascade v-model:checked-keys="formData.menuIds" clearable
          :checkable="true" :default-expand-all="false" multiple />
      </n-drawer-content>
    </n-drawer>
  </n-modal>
</template>

<script setup lang='ts'>
import {  ref, unref, computed, watch } from 'vue';
import { BusinessStatus } from "@/enum";
import { fetchAddRole, fetchRole, fetchUpdateRole } from '@/service/api/sys/role'
import { fetchDeptTree } from '@/service/api/sys/dept'
import { fetchMenuTree } from '@/service/api/sys/menu'
import { useNaiveForm } from '@/hooks/common/form';
import { FlatResponseData } from '~/packages/axios/src/type';


interface DataSource extends SysAuth.RoleInfo {
}

type Props = {
  visible: boolean,
  operateType: NaiveUI.TableOperateType,
  editKey?: Common.IdType | null
}
const props = defineProps<Props>()
interface Emits {
  (e: 'submitted'): void;
}
const emit = defineEmits<Emits>();


const visible = defineModel<boolean>('visible', {
  default: false
});
const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: '新增',
    edit: '编辑'
  };
  return titles[props.operateType];
});
const editKey = computed(() => props.editKey || null);
const { formRef, validate, restoreValidation } = useNaiveForm();
const menuTreeActive = ref<boolean>(false)
const loading = ref<boolean | undefined>(false)


const deptTree = ref<any | null>();
const menuTree = ref<any | null>();
const menuPageTree = ref<any | null>();
const statusKeyOf = BusinessStatus
const roleMenuSelectRef = ref<any | null>(null)
const dataOptions = [
  {
    label: "所有数据权限",
    value: '1',
    disabled: false
  },
  {
    label: "自定义数据权限",
    value: '2',
    disabled: false
  },
  {
    label: "本部门数据权限",
    value: '3',
    disabled: false
  },
  {
    label: "本部门及以下数据权限",
    value: '4',
    disabled: false
  },
  {
    label: "仅本人数据权限",
    value: '5',
    disabled: false
  },
]
const rules = {
  roleName: { required: true, message: "请输入角色名", trigger: 'input' },
  roleKey: { required: true, message: "请输入角色标识符", trigger: 'input' },
  homePage: { required: true, message: "角色首页不能为空", trigger: 'change' }
}
const formData = ref<DataSource>(initFormData());
function hendleCloseModal() {
  visible.value = false;
  emit("submitted")
}

function handleFetchResult(res: FlatResponseData<any, App.Service.Response<unknown>>) {
  if (!res.error) {
    hendleCloseModal()
    window.$message?.success("操作成功");
  }
}

async function handleSubmitForm() {
  await validate()
  const value = unref(formData.value)
  value.menuIds = getRoleCheckMenuIds()
  loading.value = true
  if (value.id) {
    fetchUpdateRole(formData.value).then(handleFetchResult).finally(() => {
      loading.value = false
    })
  } else {
    fetchAddRole(formData.value).then(handleFetchResult).finally(() => {
      loading.value = false
    })
  }

}

function getRoleCheckMenuIds() {
  if (!roleMenuSelectRef.value) {
    return null;
  }
  const checkData = roleMenuSelectRef.value.getCheckedData().keys
  checkData.push(...roleMenuSelectRef.value.getIndeterminateData().keys)
  return checkData
}

async function getDeptTree() {
  const { data } = await fetchDeptTree()
  deptTree.value = data
}

async function getMenuTree() {
  const { data } = await fetchMenuTree()
  menuTree.value = data
  menuPageTree.value = filterMenuPage(JSON.parse(JSON.stringify(data)))
}

function filterMenuPage(arr: SysAuth.SysMenu[]): SysAuth.SysMenu[] {

  for (let i: number = 0, len: number = arr.length; i < len && arr[i]; i++) {
    const temp = arr[i]
    if (temp.type == "B") {
      arr = arr.splice(0, i)
      i--
      continue
    }
    if (temp.children) {
      temp.children = filterMenuPage(temp.children)
    }

    arr[i].children = temp.children && temp.children.length == 0 ? undefined : temp.children
  }

  return arr;

}
function initFormData(): DataSource {
  return {
    status: BusinessStatus.Yes,
    dataScope: "1",
    homePage: '/',
  }
}

async function initEditData() {
  if (props.operateType === 'edit' && editKey.value !== null) {
    const { data } = await fetchRole(editKey.value)
    formData.value = data!;
  }
}

watch(visible, () => {
  if (visible.value) {
    restoreValidation()
    initEditData();
    getDeptTree()
    getMenuTree()
  } else {
    formData.value = initFormData()
  }
});

</script>

<style lang='scss' scoped></style>
